[HVM] Fix SMP timer issues:
authorkaf24@localhost.localdomain <kaf24@localhost.localdomain>
Fri, 27 Oct 2006 17:00:03 +0000 (18:00 +0100)
committerkaf24@localhost.localdomain <kaf24@localhost.localdomain>
Fri, 27 Oct 2006 17:00:03 +0000 (18:00 +0100)
 * Sync AP TSCs with BP at startup
 * Only halt BP TSC when descheduled
 * Correctly handle IPIs on timer vector
Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/intercept.c
xen/arch/x86/hvm/io.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/vpt.h

index f950d052957af919eba32eca03961a152a2baf55..3a9583a4c58edc03a5d1eb591e10b867f0e8e12a 100644 (file)
@@ -228,7 +228,7 @@ void hvm_do_resume(struct vcpu *v)
     hvm_stts(v);
 
     /* pick up the elapsed PIT ticks and re-enable pit_timer */
-    if ( pt->enabled && pt->first_injected ) {
+    if ( pt->enabled && v->vcpu_id == pt->bind_vcpu && pt->first_injected ) {
         if ( v->arch.hvm_vcpu.guest_time ) {
             hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
             v->arch.hvm_vcpu.guest_time = 0;
@@ -286,6 +286,9 @@ void hvm_setup_platform(struct domain* d)
     pit_init(v, cpu_khz);
     rtc_init(v, RTC_PORT(0), RTC_IRQ);
     pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); 
+
+    /* init guest tsc to start from 0 */
+    hvm_set_guest_time(v, 0);
 }
 
 void pic_irq_request(void *data, int level)
index 288cf2724d65ae204435f3d22bba0b5e26655ac6..ea6f73a51dd9eb0fb1068d73e8add3f10fbb592b 100644 (file)
@@ -325,6 +325,7 @@ struct periodic_time * create_periodic_time(
         stop_timer (&pt->timer);
         pt->enabled = 0;
     }
+    pt->bind_vcpu = 0; /* timer interrupt delivered to BSP by default */
     pt->pending_intr_nr = 0;
     pt->first_injected = 0;
     if (period < 900000) { /* < 0.9 ms */
index a1ce8ddf33cd9d4c3dfbb23d8f830e0dd34eb3a3..28f06e66a0999f09ebe4ed625addca492d35b9aa 100644 (file)
@@ -683,7 +683,8 @@ void hvm_interrupt_post(struct vcpu *v, int vector, int type)
     struct  periodic_time *pt = 
         &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
 
-    if ( pt->enabled && is_periodic_irq(v, vector, type) ) {
+    if ( pt->enabled && v->vcpu_id == pt->bind_vcpu 
+            && is_periodic_irq(v, vector, type) ) {
         if ( !pt->first_injected ) {
             pt->pending_intr_nr = 0;
             pt->last_plt_gtime = hvm_get_guest_time(v);
index 88c08024250e68def815a5635d9e3744e6e7c713..d37ab536e64597020e467d0df49cd123bf064168 100644 (file)
@@ -761,7 +761,8 @@ static void svm_freeze_time(struct vcpu *v)
 {
     struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
     
-    if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) {
+    if ( pt->enabled && pt->first_injected && v->vcpu_id == pt->bind_vcpu 
+            && !v->arch.hvm_vcpu.guest_time ) {
         v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
         stop_timer(&(pt->timer));
     }
index 3892ffa1c3ee69495cb804df7e824c1e6e7a058f..e5b96ede56f47879feecd9e5b1f683a18fbaf094 100644 (file)
@@ -314,14 +314,20 @@ static void vmx_set_host_env(struct vcpu *v)
     error |= __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
 }
 
+/* Update CR3, CR0, CR4, GDT, LDT, TR */
 static void vmx_do_launch(struct vcpu *v)
 {
-/* Update CR3, CR0, CR4, GDT, LDT, TR */
     unsigned int  error = 0;
     unsigned long cr0, cr4;
 
-    if (v->vcpu_id == 0)
+    if ( v->vcpu_id == 0 )
         hvm_setup_platform(v->domain);
+    else {
+        /* Sync AP's TSC with BSP's */
+        v->arch.hvm_vcpu.cache_tsc_offset = 
+            v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
+        hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+    }
 
     __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : );
 
@@ -360,9 +366,6 @@ static void vmx_do_launch(struct vcpu *v)
     __vmwrite(HOST_CR3, v->arch.cr3);
 
     v->arch.schedule_tail = arch_vmx_do_resume;
-
-    /* init guest tsc to start from 0 */
-    hvm_set_guest_time(v, 0);
 }
 
 /*
index ac1be73556fab38e77ea4f4b7f535da16366bcd4..41285d6f3cc188ca8dbcf0b7feb135751c556b1d 100644 (file)
@@ -458,7 +458,8 @@ static void vmx_freeze_time(struct vcpu *v)
 {
     struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
     
-    if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) {
+    if ( pt->enabled && pt->first_injected && v->vcpu_id == pt->bind_vcpu
+            && !v->arch.hvm_vcpu.guest_time ) {
         v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
         stop_timer(&(pt->timer));
     }
@@ -1972,6 +1973,13 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
 
     switch (regs->ecx) {
     case MSR_IA32_TIME_STAMP_COUNTER:
+        {
+            struct periodic_time *pt =
+                &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+            if ( pt->enabled && pt->first_injected 
+                    && v->vcpu_id == pt->bind_vcpu ) 
+                pt->first_injected = 0;
+        }
         hvm_set_guest_time(v, msr_content);
         break;
     case MSR_IA32_SYSENTER_CS:
index ada8936af7072752e7d87b75edca7e723c90956d..b4492e1d5945541ef62e2d326604953367c269a1 100644 (file)
@@ -91,6 +91,7 @@ struct periodic_time {
     char one_shot;              /* one shot time */
     char irq;
     char first_injected;        /* flag to prevent shadow window */
+    u32 bind_vcpu;              /* vcpu timer interrupt delivers to */
     u32 pending_intr_nr;        /* the couner for pending timer interrupts */
     u32 period;                 /* frequency in ns */
     u64 period_cycles;          /* frequency in cpu cycles */